package com.ruoyi.web.controller.tool;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;

/**
 * netty 服务端
 *
 NettyEchoServer 类是整个服务器程序的入口。
 使用两个EventLoopGroup来管理事件循环，分别对应于接受新连接的“Boss”线程组和处理已连接客户端请求的“Worker”线程组。
 ServerBootstrap 类用于配置和绑定服务器端口，并设置当有新的连接进来时如何初始化子通道（即每个客户端连接对应的通道）。
 EchoServerHandler 是自定义的ChannelHandler，它继承自 SimpleChannelInboundHandler<String>，用于处理从客户端接收到的消息。在 channelRead0 方法中，服务器将收到的消息原样回送给客户端。
 * @author Hack2003
 * @date 2024/3/13 17:17
 **/
public class NettyEchoServer {
    public static void main(String[] args) throws Exception {
        //创建Boss EventLoopGroup,负责接收新的连接请求
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //创建Worker EventLoopGroup,负责处理已建立连接的网络读写事件
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //创建ServerBootstrap对象,用于配置和绑定服务器端口
            ServerBootstrap b = new ServerBootstrap();
            //设置EventLoopGroup和Channel类型和ChannelInitializer
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //添加自定义的EchoServerHandler到每个新连接的ChannelPipeline中
                            //ch.pipeline().addLast(new StringDecoder(), new StringEncoder(), new EchoServerHandler());
                            //添加解码器，半接收到的字节流解码为字符串
                            ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
                            //添加编码器，将响应的字符串重新编码为字节流以便 发送给客户端
                            ch.pipeline().addLast( new StringEncoder(CharsetUtil.UTF_8));
                            //添加自定义业务处理器，这里负责接收并原样返回消息
                            ch.pipeline().addLast(new EchoServerHandler());

                        }
                    });

            ChannelFuture f = b.bind(8080).sync();
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static class EchoServerHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            System.out.println("服务端接收到消息，内容为："+msg);
            ctx.write("服务端接收到消息，并将发的消费，返回给客户端，内容为："+msg); // 将接收到的消息原样写回
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) {
            //在完成消息读取后调用flush方法，确保数据被发送出去
            ctx.flush();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            //异常处理等其它方法
            cause.printStackTrace();
            ctx.close();
        }
    }
}
